home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_075 / dum2 / src / dum2.mod < prev    next >
Text File  |  1992-05-06  |  19KB  |  666 lines

  1. MODULE DuM2;
  2.  
  3. (*      ANOTHER DIRECTORY Utility. This one in Modula-2      *)
  4.  
  5. (* ALL THE MODULES ARE $A+ SINCE CODE IS NOW ONLY 24800 BYTES OR SO.
  6.    IF IT GROWS A LOT, THEY MAY HAVE TO BE CHANGED TO $Q+
  7. *)
  8.  
  9. (*$S-*)(*$T-*)(*$A+*)
  10.  
  11. (*
  12.         This is the main module for DirUtil (works from CLI or WB now)
  13.  
  14.         Written: 3/21/87 by Greg Browne
  15.         Modified: by Greg Browne
  16.         1.1 - Quicksort added - sized down to 300 files for memory saving
  17.                Clean up booboos. (4/12/87)
  18.  
  19.         1.2 - EDIT is EXECUTED only, not RUN now & SHOW also - prevents DOS
  20.               from trying to get too many things going at once since when
  21.               RUN is EXEC'ed, it tries the next one immediately.
  22.               Put quotes around filename to allow for multiple word names
  23.  
  24.         1.3 - Minor clean up (4/15/87)
  25.  
  26.         1.4 - Added EXEC f-R & EXEC R-f - removed UnARC (redundant)
  27.               Also cleaned up minor message display. (4/18/87)
  28.  
  29.         1.5 - Added WB Startup  thanks to Richie Bielack's example (4/20/87)
  30.               HAPPY EASTER!
  31.  
  32.         Compiled on TDI's Modula-2 Compiler version 2.20a
  33.  
  34.  
  35.         If you modify this program and change version numbers,
  36.         remember to change the string literal for the window title
  37.         which is located in MAIN control area at end of program.
  38.  
  39.         You may modify and/or use this program, but please give credit
  40.         where it is due (not only to me, but all the others I drew from)
  41.  
  42. *)
  43.  
  44. (*  M2: normal library modules *)
  45.  
  46. FROM SYSTEM             IMPORT  ADR, NULL,TSIZE,ADDRESS;
  47. FROM Intuition          IMPORT  IDCMPFlagSet,GadgetPtr,IDCMPFlags;
  48. FROM Ports              IMPORT  WaitPort;
  49. FROM Memory             IMPORT  AllocMem,FreeMem,MemReqSet,MemPublic,
  50.                                 MemClear;
  51. FROM DOSLibrary         IMPORT  DOSBase;
  52. FROM Libraries          IMPORT  CloseLibrary;
  53. FROM DOSFiles           IMPORT  Lock,Unlock,AccessRead,FileLock,CurrentDir,
  54.                                 IoErr,InfoData,Info,CreateDir,DeleteFile,
  55.                                 Close,Open,ModeNewFile,FileHandle;
  56. FROM Strings            IMPORT  Concat,Length,Assign,Insert;
  57.  
  58. (* Richie Bielack's WorkBench startup module *)
  59.  
  60. FROM WBStart            IMPORT  GetWBStartUpMsg,ReturnWBStartUpMsg;
  61.  
  62. (* My Du Specific library modules *)
  63.  
  64. FROM DuWindow           IMPORT  GadgetNames,DuWindowPtr,IOString,DuGads,
  65.                                 CloseDuWindow,OpenDuWindow,SlidePot;
  66. FROM DuDir              IMPORT  DirEntries,DirTable,ReadDirectory,QSort,
  67.                                 DisplayFiles,NewDir,ClearTable;
  68. FROM DuMisc             IMPORT  CharPtr,MyMsg,MyClass,MyGadPtr,GadGot,
  69.                                 MyX,MyY,Gp,CheckMessages,DoFileLook,
  70.                                 ReplaceRSDM,StringIt,DuExec,OutHandle,
  71.                                 AskForConfirm,DuMoveFile,DuFileTwiddle;
  72.  
  73. (* Variables not needed in other modules *)
  74.  
  75. VAR
  76.   Curfirst      : CARDINAL;              (* current first on screen *)
  77.   Curdir,                                (* current dir name        *)
  78.   Reqdir        : ARRAY [0..90] OF CHAR; (* requested dir name      *)
  79.   Entrydirlock,                          (* For later               *)
  80.   Lastdirlock,                           (* Temporary may use later *)
  81.   Curdirlock,                            (* Current directory lock  *)
  82.   Reqdirlock    : FileLock;              (* Requested dir lock      *)
  83.   GpCp          : CharPtr;               (* General purpose pointer *)
  84.   wbmsg         : ADDRESS;               (* WB message if any       *)
  85.   inf           : POINTER TO InfoData;   (* for getting INFO        *)
  86.  
  87.  
  88. (* =================================================================*)
  89.  
  90. (* Little cleanup routine to make sure some junk isn't displayed *)
  91.  
  92. PROCEDURE RemoveZaps;
  93. VAR i,j:CARDINAL;
  94. BEGIN
  95.   j := 0;
  96.   FOR i := 1 TO DirEntries DO
  97.     IF (DirTable[i]^.FileName[0] = 177C) THEN INC(j) END;
  98.   END;
  99.   IF j > 0 THEN QSort; DEC(DirEntries,j) END;
  100. END RemoveZaps;
  101.  
  102. (* All the 'ok' and ABORT messages call here to keep a million OK
  103.    and Operation ABORTED constants from being put into the program
  104. *)
  105.  
  106. PROCEDURE SayOK;
  107. BEGIN
  108.    ReplaceRSDM(msg,"OK");
  109. END SayOK;
  110.  
  111.  
  112. PROCEDURE SayAbort;
  113. BEGIN
  114.    ReplaceRSDM(msg,"Operation INTERRUPTED");
  115. END SayAbort;
  116.  
  117.  
  118. PROCEDURE EndIt(er:LONGINT);
  119. BEGIN
  120.   IF er = 0 THEN SayOK
  121.    ELSIF er = -1 THEN ReplaceRSDM(msg,"Improper Dest string")
  122.     ELSIF er = -2 THEN SayAbort
  123.      ELSE DisplayError("Couldn't finish",er);
  124.   END;
  125. END EndIt;
  126.  
  127.  
  128. PROCEDURE GetReqDir():BOOLEAN;
  129. (* Get directory in Reqdir - or say couldn't by return of FALSE *)
  130. BEGIN
  131.   Reqdirlock := Lock(Reqdir,AccessRead);
  132.   IF (Reqdirlock = 0) THEN RETURN FALSE END;
  133.   IF NOT ReadDirectory(Reqdirlock) THEN
  134.     Unlock(Reqdirlock);
  135.     RETURN FALSE
  136.   ELSE
  137.     IF DirEntries > 1 THEN QSort END;
  138.     NewDir;
  139.     Lastdirlock := CurrentDir(Reqdirlock);
  140.     IF Lastdirlock <> 0 THEN Unlock(Lastdirlock) END;
  141.     Curdirlock := Reqdirlock;
  142.     Assign(Curdir,Reqdir);
  143.     Curfirst := 1;
  144.     RETURN TRUE
  145.   END;
  146. END GetReqDir;
  147.  
  148.  
  149. PROCEDURE RedisplayFiles(force:BOOLEAN);
  150. (* If force=TRUE then will be redisplayed anyhow, otherwise only if
  151.    more than a screenfull exist
  152. *)
  153. VAR Vpot : CARDINAL;temp:LONGCARD;
  154. BEGIN
  155.   IF (DirEntries > 15) OR (force) THEN
  156.     Vpot := SlidePot();
  157.     temp := LONGCARD(DirEntries - 15);
  158.     temp := temp * LONGCARD(Vpot);
  159.     Curfirst := CARDINAL(temp DIV 0FFFFH)+1;
  160.     IF Vpot = 0FFFFH THEN Curfirst := 999 END;
  161.     IF Curfirst > DirEntries - 14 THEN Curfirst := DirEntries - 14 END;
  162.     IF Curfirst < 1 THEN Curfirst := 1 END;
  163.     DisplayFiles(Curfirst);
  164.   END;
  165. END RedisplayFiles;
  166.  
  167.  
  168. PROCEDURE GetDev;
  169. (* Get the device hit *)
  170. VAR i:CARDINAL;
  171. BEGIN
  172.   GpCp :=CharPtr(DuGads[GadGot].GadgetText^.IText);
  173.   i := 0;
  174.   DEC(GpCp);
  175.   REPEAT
  176.     INC(GpCp);
  177.     Reqdir[i] := GpCp^;
  178.     INC(i);
  179.   UNTIL (GpCp^ = 0C);
  180.   IF GetReqDir() THEN ReplaceRSDM(source,Reqdir) END;
  181. END GetDev;
  182.  
  183.  
  184. PROCEDURE GetSource;
  185. VAR i : CARDINAL;
  186. (* Get the IOString[source] directory if possible
  187.    Has several bailout alternatives
  188. *)
  189. BEGIN
  190.   i := 0;
  191.   WHILE (IOString[source][i] > 40C) AND (i < 90) DO
  192.     Reqdir[i] := IOString[source][i];
  193.     INC(i);
  194.   END;
  195.   Reqdir[i] := 0C;
  196.   IF (Reqdir[0] = 0C) THEN Assign(Reqdir,":") END;
  197.   (* If can't get then switch back to currently selected directory *)
  198.   IF NOT GetReqDir() THEN
  199.     DisplayError("Couldn't get requested directory",IoErr());
  200.     Assign(Reqdir,Curdir);
  201.     IF NOT GetReqDir() THEN
  202.       DisplayError("Couldn't switch back - going to ram:",IoErr());
  203.       GadGot := ram;
  204.       GetDev;
  205.     END;
  206.   ReplaceRSDM(source,Curdir);
  207.   END;
  208.   SayOK;
  209. END GetSource;
  210.  
  211. PROCEDURE GetParent;
  212. (* Go to parent or root depending on the gadget hit and in GadGot *)
  213. VAR i, l:CARDINAL; Stop:BOOLEAN;
  214. BEGIN
  215.   Assign(Reqdir,IOString[source]);
  216.   l := Length(Reqdir);
  217.   Stop := FALSE;
  218.   REPEAT
  219.     DEC(l);
  220.     IF (Reqdir[l] = "/") AND (GadGot = parent) THEN
  221.       Reqdir[l] := 0C; Stop := TRUE;
  222.     ELSIF (Reqdir[l] = ":") THEN
  223.       Reqdir[l+1] := 0C; Stop := TRUE;
  224.     END;
  225.   UNTIL (l=0) OR (Stop);
  226.   IF (Reqdir[0] = 0C) THEN Assign(Reqdir,":") END;
  227.   ReplaceRSDM(source,Reqdir);
  228.   GetSource;
  229. END GetParent;
  230.  
  231.  
  232. PROCEDURE SwapStrings(g:GadgetNames);
  233. (* does the shuffling and reselects directory if necessary *)
  234. BEGIN
  235.   IF    g = rtod THEN ReplaceRSDM(dest,  IOString[run]   )
  236.   ELSIF g = rtos THEN ReplaceRSDM(source,IOString[run]   )
  237.   ELSIF g = stod THEN ReplaceRSDM(dest,  IOString[source])
  238.   ELSIF g = stor THEN ReplaceRSDM(run,   IOString[source])
  239.   ELSIF g = dtor THEN ReplaceRSDM(run,   IOString[dest]  )
  240.   ELSIF g = dtos THEN ReplaceRSDM(source,IOString[dest]  )
  241.   ELSIF g = swapsd THEN
  242.         Assign(Gp,IOString[source]);
  243.         ReplaceRSDM(source,IOString[dest]);
  244.         ReplaceRSDM(dest,Gp);
  245.   ELSIF g = swaprd THEN
  246.         Assign(Gp,IOString[run]);
  247.         ReplaceRSDM(run,IOString[dest]);
  248.         ReplaceRSDM(dest,Gp);
  249.   ELSE  Assign(Gp,IOString[source]);  (* swaprs *)
  250.         ReplaceRSDM(source,IOString[run]);
  251.         ReplaceRSDM(run,Gp);
  252.   END;
  253.   CASE g OF
  254.     rtos,
  255.     dtos,
  256.     swaprs,
  257.     swapsd      :   GetSource;          |
  258.   ELSE
  259.   END;
  260. END SwapStrings;
  261.  
  262.  
  263. PROCEDURE SelectDir(n:CARDINAL);
  264. (* Select a directory and possibly enter it *)
  265. VAR i,j:CARDINAL;
  266. BEGIN
  267.   FOR i := 1 TO DirEntries DO
  268.     WITH DirTable[i]^ DO
  269.       IF IsDir THEN
  270.         IF i=n THEN
  271.           IsSelected := NOT IsSelected;
  272.         ELSE
  273.           IsSelected := FALSE
  274.         END;
  275.       END;
  276.     END;
  277.   END;
  278.   RedisplayFiles(TRUE);
  279.   IF (DirTable[n]^.IsSelected) THEN
  280.     ReplaceRSDM(msg,"Click it again to ENTER the directory");
  281.     REPEAT (* *) UNTIL CheckMessages();
  282.     j := CARDINAL((MyY - 24) DIV 8) + Curfirst;
  283.     IF (GadGot = filewindow) AND (j = n) THEN
  284.       SayOK;
  285.       Assign(Gp,IOString[source]);
  286.       IF Gp[Length(Gp)-1] <> ":" THEN
  287.         Concat(Gp,"/",Gp);
  288.       END;
  289.       Concat(Gp,DirTable[n]^.FileName,Gp);
  290.       ReplaceRSDM(source,Gp);
  291.       GetSource;
  292.     ELSE
  293.       SayAbort
  294.     END;
  295.   END;
  296.   RedisplayFiles(TRUE);
  297. END SelectDir;
  298.  
  299.  
  300. PROCEDURE SelectFile;
  301. (* find, and toggle selection, of a file - branches to SelectDir if
  302.    the hit is over a directory name
  303. *)
  304. VAR pos : CARDINAL;
  305. BEGIN
  306.   pos := CARDINAL((MyY - 24) DIV 8) + Curfirst;
  307.   IF pos <= DirEntries THEN
  308.     WITH DirTable[pos]^ DO
  309.       IF IsDir THEN
  310.         SelectDir(pos)
  311.       ELSE
  312.         IsSelected := NOT IsSelected;
  313.         DisplayFiles(Curfirst);
  314.       END
  315.     END;
  316.   END;
  317.   SayOK;
  318. END SelectFile;
  319.  
  320.  
  321. PROCEDURE DisplayError(VAR a:ARRAY OF CHAR; de:LONGINT);
  322. (* display error message with DOS error code *)
  323. VAR v:ARRAY[0..33] OF CHAR; dx:LONGCARD;
  324. BEGIN
  325.   Assign(Gp,a);
  326.   IF de > 0 THEN
  327.     dx := LONGCARD(de);
  328.     Concat(Gp," - DOS error ",Gp);
  329.     IF StringIt(dx,v) THEN END;
  330.     Concat(Gp,v,Gp);
  331.   END;
  332.   ReplaceRSDM(msg,Gp);
  333. END DisplayError;
  334.  
  335.  
  336. PROCEDURE SelectAll(v:BOOLEAN);
  337. (* Mass select of all non-directory filenames in the current list
  338.    if v is FALSE it is a mass clear instead
  339. *)
  340. VAR i:CARDINAL;
  341. BEGIN
  342.   FOR i := 1 TO DirEntries DO
  343.     IF DirTable[i]^.IsDir = FALSE THEN DirTable[i]^.IsSelected := v END;
  344.    END;
  345.   DisplayFiles(Curfirst);
  346.   SayOK;
  347. END SelectAll;
  348.  
  349.  
  350. PROCEDURE AlreadyGotDest():BOOLEAN;
  351. (* Check to see if the destination path or file exists already
  352.    to prevent rename or makedir of duplicate
  353. *)
  354. VAR l:FileLock;
  355. BEGIN
  356.   l := Lock(IOString[dest],AccessRead);
  357.   IF l <> 0 THEN
  358.     Unlock(l);
  359.     DisplayError("File or directory exists",IoErr());
  360.     RETURN TRUE;
  361.   END;
  362.   RETURN FALSE;
  363. END AlreadyGotDest;
  364.  
  365.  
  366. PROCEDURE DoRename;
  367. (* Rename a file [first one found selected] to the dest gadget name
  368.    This routine prevents renaming for CASE changes
  369.    i.e. DOIT.ARC to DoIt.arc - sorry, DOS doesn't care, I do.
  370. *)
  371.  
  372. VAR i,n:CARDINAL;er:LONGINT;l :FileLock;
  373. BEGIN
  374.   n := 0;i := 0;
  375.   WHILE (n = 0) AND (i < DirEntries) DO
  376.     INC(i);
  377.     IF DirTable[i]^.IsSelected THEN n := i END;
  378.   END;
  379.   IF (n > 0) AND (NOT AlreadyGotDest()) THEN
  380.     er := DuMoveFile(DirTable[i]^.FileName,IOString[dest]);
  381.     IF er = 0 THEN
  382.       GetSource;
  383.       SayOK;
  384.     ELSE
  385.       Insert(" to ",Gp,0);
  386.       Insert(DirTable[i]^.FileName,Gp,0);
  387.       Insert("Couldn't rename ",Gp,0);
  388.       DisplayError(Gp,er);
  389.     END;
  390.   ELSIF (IOString[dest][0] < 41C) THEN
  391.     EndIt(LONGINT(-2))
  392.   END;
  393. END DoRename;
  394.  
  395.  
  396. PROCEDURE DeleteDirectory;
  397. (* Delete a directory if not in use or filled
  398.     proposed option is delete even if filled - sort of a mass directory
  399.     kill
  400. *)
  401. VAR i,n:CARDINAL;er:LONGINT;l :FileLock;
  402. BEGIN
  403.   n := 0;i := 0;
  404.   WHILE (n = 0) AND (i < DirEntries) DO
  405.     INC(i);
  406.     IF (DirTable[i]^.IsSelected) AND (DirTable[i]^.IsDir) THEN n := i END;
  407.   END;
  408.   IF (n > 0) THEN
  409.     IF DeleteFile(DirTable[n]^.FileName) THEN
  410.       GetSource;
  411.       SayOK;
  412.     ELSE
  413.       er := IoErr();
  414.       Assign(Gp,DirTable[i]^.FileName);
  415.       IF (er = 216) THEN
  416.         Concat(Gp," not empty",Gp)
  417.       ELSE
  418.         Insert("Couldn't delete ",Gp,0)
  419.       END;
  420.       DisplayError(Gp,er);
  421.     END;
  422.   END;
  423. END DeleteDirectory;
  424.  
  425. PROCEDURE MakeNewDir;
  426. (* Make new directory if proposed name [dest] not already there
  427.    or if [dest] is not null.  If no full path is given, it will
  428.    make the directory relative to the [source] gadget
  429. *)
  430. VAR l:FileLock;
  431. BEGIN
  432.   IF IOString[dest][0] < 41C THEN
  433.     EndIt(LONGINT(-1))
  434.   ELSIF (NOT AlreadyGotDest()) THEN
  435.     l := CreateDir(IOString[dest]);
  436.     IF (l = 0) THEN
  437.       DisplayError("Couldn't create directory",IoErr());
  438.     ELSE
  439.       Unlock(l);
  440.       SayOK;
  441.       GetSource;
  442.     END;
  443.   END;
  444. END MakeNewDir;
  445.  
  446. PROCEDURE FillInfo(l:FileLock;VAR s,n:ARRAY OF CHAR);
  447. VAR by:LONGCARD;
  448. BEGIN
  449.   IF (l <> 0) THEN
  450.     IF Info(l,inf^) THEN
  451.       WITH inf^ DO
  452.         IF StringIt((idNumBlocks-idNumBlocksUsed)*idBytesPerBlock,n) THEN END;
  453.         Insert(s,n,0);
  454.         Concat(n," bytes free  ",n);
  455.       END;
  456.     END;
  457.   END;
  458. END FillInfo;
  459.  
  460. PROCEDURE GiveInfo;
  461. (* Gives info on both source and dest - want to add volume name
  462.    print as well later.
  463. *)
  464. BEGIN
  465.   Gp := "";
  466.   Reqdir := "";
  467.   inf := AllocMem(TSIZE(InfoData),MemReqSet{MemPublic,MemClear});
  468.   IF (inf # NULL) THEN
  469.     FillInfo(Curdirlock,"Source: ",Gp);
  470.     Reqdirlock := Lock(IOString[dest],AccessRead);
  471.     FillInfo(Reqdirlock,"Dest: ",Reqdir);
  472.     IF Reqdirlock <> 0 THEN Unlock(Reqdirlock) END;
  473.     FreeMem(inf,TSIZE(InfoData));
  474.     Concat(Gp,Reqdir,Gp);
  475.     ReplaceRSDM(msg,Gp);
  476.   ELSE
  477.     DisplayError("Couldn't get info block",IoErr());
  478.   END;
  479. END GiveInfo;
  480.  
  481.  
  482. PROCEDURE WhatBytes;
  483. (* Show total bytes and files for selected filenames
  484. *)
  485. VAR i,j:CARDINAL;b,f:LONGCARD; v:ARRAY[0..33] OF CHAR;
  486. BEGIN
  487.   f := 0;b := 0;
  488.   FOR i := 1 TO DirEntries DO
  489.     WITH DirTable[i]^ DO
  490.       IF (IsDir = FALSE) AND (IsSelected) THEN
  491.         INC(f);
  492.         b := b + LONGCARD(DirTable[i]^.FileSize) + 512
  493.       END;
  494.     END;
  495.   END;
  496.   IF StringIt(b,v) THEN END;
  497.   Assign(Gp,v);
  498.   Concat(Gp," bytes (incl. FileInfoBlocks) in ",Gp);
  499.   IF StringIt(f,v) THEN END;
  500.   Concat(Gp,v,Gp);
  501.   Concat(Gp," files.",Gp);
  502.   ReplaceRSDM(msg,Gp);
  503. END WhatBytes;
  504.  
  505.  
  506. PROCEDURE DoCopy(wcopy,wdel:BOOLEAN);
  507. (* direction handler and exit handler for the Twiddle procedure
  508.    handles COPY, COPYDEL, ZAPFILE, and MOVE
  509. *)
  510. VAR er:LONGINT;
  511. BEGIN
  512.   er := DuFileTwiddle(wcopy,wdel);
  513.   RemoveZaps;
  514.   RedisplayFiles(TRUE);
  515.   EndIt(er);
  516. END DoCopy;
  517.  
  518.  
  519. PROCEDURE DoDestruct(g:GadgetNames);
  520. (* Handler for all the destructive stuff
  521.    COPYDEL, ZAPFILE, and DELDIR all go through here to confirm
  522. *)
  523. BEGIN
  524.   AskForConfirm;
  525.   REPEAT (* waiting patiently *) UNTIL CheckMessages();
  526.   IF (GadGot <> g) THEN
  527.     SayAbort;
  528.   ELSE
  529.    IF       g = copydel THEN DoCopy(TRUE,TRUE)
  530.      ELSIF  g = deldir  THEN DeleteDirectory
  531.       ELSIF g = zapfile THEN DoCopy(FALSE,TRUE)
  532.     END;
  533.   END;
  534. END DoDestruct;
  535.  
  536.  
  537.  
  538. (* all GadgetUp messages received in the main routine (LOOP) are sent
  539.    here for processing - further branches handle the various work
  540. *)
  541.  
  542. PROCEDURE ProcessGadgets(gptr:GadgetPtr):BOOLEAN;
  543. BEGIN
  544.  
  545.   (* First check for device gadgets since in the GadgetNames, up to vd0
  546.         all are 'get-device' commands *)
  547.   IF GadGot <= vd0 THEN
  548.     GetDev;
  549.     RETURN TRUE;        (* no need to waste time looking at other list *)
  550.   END;
  551.  
  552.   (* next multiple gadgets using same branch routine
  553.          followed by  gadgets with separate routines  *)
  554.  
  555.   CASE GadGot OF
  556.     deldir,
  557.     copydel,
  558.     zapfile     : DoDestruct(GadGot);           |
  559.     dtor,
  560.     dtos,
  561.     rtod,
  562.     rtos,
  563.     stor,
  564.     stod,
  565.     swaprd,
  566.     swaprs,
  567.     swapsd      : SwapStrings(GadGot);          |
  568.     arc,
  569.     edit,
  570.     execfr,
  571.     execrf,
  572.     runfr,
  573.     runrf,
  574.     show        : EndIt(DuExec());GetSource;    |
  575.     type,
  576.     htype,
  577.     print,
  578.     hprint      : IF DoFileLook() THEN END;
  579.                   RedisplayFiles(TRUE);         |
  580.     run,
  581.     dest        : RETURN TRUE;                  | (* simply ignore changes *)
  582.     move        : DoCopy(FALSE,FALSE);          |
  583.     makedir     : MakeNewDir;                   |
  584.     filewindow  : SelectFile;                   |
  585.     rename      : DoRename;                     |
  586.     source      : GetSource;                    |
  587.     copy        : DoCopy(TRUE,FALSE);           |
  588.     info        : GiveInfo;                     |
  589.     parent,
  590.     root        : GetParent;                    |
  591.     slider      : RedisplayFiles(FALSE);        |
  592.     select      : SelectAll(TRUE);              |
  593.     clear       : SelectAll(FALSE);             |
  594.     bytes       : WhatBytes;                    |
  595.   ELSE
  596.     ReplaceRSDM(msg,"Sorry, maybe next revision!");
  597.   END;
  598.   RETURN TRUE;
  599. END ProcessGadgets;
  600.  
  601. (* ---------------------------*)
  602.  
  603. (* This is the main operating routine.  A double loop is used, although
  604.    a single WaitPort loop would have worked.  Since I wanted a separate
  605.    CheckMessages routine which may have NULL results, I did it this
  606.    way.  Why not?
  607. *)
  608.  
  609. PROCEDURE GetNextMessage;
  610. BEGIN
  611.  
  612.             (* Outer loop forces wait for message from intuition *)
  613.  
  614.  LOOP
  615.   MyMsg := WaitPort(DuWindowPtr^.UserPort);
  616.  
  617.        (* Inner loop gets messages and processes them until NULL message *)
  618.  
  619.   LOOP
  620.    IF NOT CheckMessages() THEN EXIT END;
  621.    IF MyClass = IDCMPFlagSet{CloseWindowFlag} THEN
  622.      RETURN     (**** ONLY EXIT so Get out of here ****)
  623.    ELSIF (MyClass = IDCMPFlagSet{GadgetUp}) AND ProcessGadgets(MyGadPtr) THEN
  624.    ELSIF (MyClass = IDCMPFlagSet{ResfreshWindow}) THEN
  625.      RedisplayFiles(TRUE)  (* Rest of screen is self-refreshing *)
  626.    END
  627.   END (* Inner LOOP *)
  628.  
  629.  END; (* Outer LOOP *)
  630.  
  631. END GetNextMessage;
  632.  
  633.                                   (********)
  634.                                   (* MAIN *)
  635.                                   (********)
  636.  
  637. BEGIN
  638.      wbmsg := GetWBStartUpMsg();
  639.      (* If running from WB then  an output window *)
  640.      IF wbmsg <> NULL THEN
  641.        OutHandle := Open("RAW:0/150/640/49/DuOutputWindow",ModeNewFile)
  642.      ELSE
  643.        OutHandle := FileHandle(0)
  644.      END;
  645.      (* Try to open the window - run if successful [log to ram first] *)
  646.      (* The literal below is the window title bar display             *)
  647.  
  648.   IF OpenDuWindow("DirUtil v1.5 [TDI Modula-2] - by Greg Browne") THEN
  649.     GadGot := ram;
  650.     GetDev;
  651.     GetNextMessage
  652.   END;
  653.      (* GO HERE ON FAILURE OR FINISH (CloseWindowFlag)               *)
  654.      (* First free the memory used by the DirTable                   *)
  655.   ClearTable;
  656.      (* Close window, graphics library and intuition library if open *)
  657.   CloseDuWindow;
  658.      (* Unlock the directory lock you're holding (if any)            *)
  659.      (* Remember to close DOS library too if open                    *)
  660.   IF Curdirlock <> 0 THEN Unlock(Curdirlock) END;
  661.   IF DOSBase <> 0 THEN CloseLibrary(DOSBase) END;
  662.   IF OutHandle <> 0 THEN Close(OutHandle) END;
  663.   ReturnWBStartUpMsg;
  664. END DuM2.
  665.  
  666.